package com.ycwl.aiLive_2d.utils;

import com.ycwl.aiLive_2d.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.math3.util.Precision;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import java.io.File;
import java.net.URL;
import java.util.*;

/**
 * @author songmingsong
 * @date 2023/7/10
 */
@Slf4j
public class AudioUtils {
    /**
     * 播放音频文件
     *
     * @param tmpAudioPath
     */
    public static void playAudio(String tmpAudioPath) {
        try {
            Clip clip = AudioSystem.getClip();
            AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File(tmpAudioPath));
            clip.open(audioInputStream);
            clip.start();
            Thread.sleep(100);
            clip.drain();
            clip.close();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException("音频播放异常", 5001);
        }
    }

    /**
     * 获取音频文件口型数据
     *
     * @param tmpAudioPath
     * @return
     */
    public static List<Double> processAudio(String tmpAudioPath, String uid) {
        log.info("[ 线程 ] ->开始解析以下数据->{}", tmpAudioPath);
        List<Double> list = new ArrayList<>();
        try {
            double[] x, normalizedX;
            double minValue, maxValue;

            File file = new File(tmpAudioPath);
            AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file);

            byte[] audioBytes = new byte[(int) file.length()];
            audioInputStream.read(audioBytes);
            audioInputStream.close();

            x = new double[audioBytes.length / 2];
            for (int i = 0, j = 0; i < audioBytes.length; i += 2, j++) {
                x[j] = ((audioBytes[i]) & 0xff) | ((audioBytes[i + 1]) << 8);
            }

            minValue = Double.MAX_VALUE;
            maxValue = Double.MIN_VALUE;

            for (double sample : x) {
                if (sample < minValue) {
                    minValue = sample;
                }
                if (sample > maxValue) {
                    maxValue = sample;
                }
            }

            normalizedX = new double[x.length];
            for (int i = 0; i < x.length; i++) {
                normalizedX[i] = (x[i] - minValue) / (maxValue - minValue);
            }

            for (int i = 0; i < normalizedX.length; i++) {
                normalizedX[i] = Math.log(normalizedX[i]) + 1;
            }

            double maxVal = Double.MIN_VALUE;
            for (double value : normalizedX) {
                if (value > maxVal) {
                    maxVal = value;
                }
            }

            for (int i = 0; i < normalizedX.length; i++) {
                normalizedX[i] = (normalizedX[i] / maxVal) * 1.2;
            }

            double start = System.currentTimeMillis();
            int index = 0;
            /**
             * 播放音频文件
             */
            //playAudio(tmpAudioPath);

            while (((System.currentTimeMillis() - start) / 1000) < x.length / 8000) {
                if (index < normalizedX.length) {
                    double it = normalizedX[index];
                    if (it < 0) {
                        it = 0;
                    }
                    list.add(Precision.round(it, 2));
                    Thread.sleep(100);
                    index += 8000;
                }
            }
            //list.add(0.00);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException("嘴行弧度转换异常", 5001);
        }
        return list;
    }

    /**
     * 获取wav的时长
     *
     * @param wavFilePath
     * @return
     */
    public static Double getVoiceLength(String wavFilePath) {
        if (wavFilePath == null || wavFilePath.length() == 0) {
            return 0D;
        }
        String bath = wavFilePath.split(":")[0];
        Clip clip = null;
        try {
            clip = AudioSystem.getClip();
            AudioInputStream ais;
            if ("http".equals(bath.toLowerCase()) || "https".equals(bath.toLowerCase())) {
                ais = AudioSystem.getAudioInputStream(new URL(wavFilePath));
            } else {
                ais = AudioSystem.getAudioInputStream(new File(wavFilePath));
            }
            clip.open(ais);
            return clip.getMicrosecondLength() / 1000000D;
        } catch (Exception e) {
            throw new BaseException("文件时长获取失败", 5001);
        } finally {
            if (clip != null) {
                clip.close();
            }
        }
    }
}
